﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
[Serializable]
public class SimpleState{
	[SerializeField]
	public string stateName;
	Action onenter;
	Action<float> onupdate;
	Action onleave;
	bool isEntered;
	bool isLeaved;
	public SimpleState(){
	}

	public SimpleState(string _s){
		stateName = _s;
	}

	public virtual void SetAction(Action _onenter = null,Action<float> _onupdate = null,Action _onleave = null){
		onenter = _onenter;
		onupdate = _onupdate;
		onleave = _onleave;
	}

	public void BindEvent(Action _onenter = null, Action _onleave = null, Action<float> _onupdate = null){
		if (_onenter != null)
			onenter += _onenter;
		if (_onleave != null)
			onleave += _onleave;
		if (_onupdate != null)
			onupdate += _onupdate;
	}

	public virtual void OnLeave ()
	{
		if (onleave != null && !isLeaved) {
			onleave ();
		}
		isEntered = false;
		isLeaved = true;
	}

	public virtual void OnEnter ()
	{
		if (onenter != null && !isEntered)
			onenter ();
		isEntered = true;
		isLeaved = false;
	}

	public virtual void OnUpdate(float dt){
		if (onupdate != null)
			onupdate (dt);
	}
}

public struct StateTransactionData{
	public float time;
	public SimpleState state;
	public StateTransactionData (float _t, SimpleState _ss){
		time = _t;
		state = _ss;
	}
}

[Serializable]
public class SimpleFSM{
	/// <summary>
	/// 所有状态
	/// </summary>
	Dictionary<string, SimpleState> _states = new Dictionary<string, SimpleState>();
	/// <summary>
	/// 状态条件转移
	/// </summary>
	List<StateTransactionData> _stateTransaction = new List<StateTransactionData>();
	float globalTime;
	public float stateTime;
	public float pauseTime;
	bool isPause;

	[SerializeField]
	SimpleState _currentState;
	[SerializeField]
	SimpleState _lastCurrentState;

	SimpleState currentState{
		get{ 
			return _currentState;
		}
		set{ 
			if (_currentState != null) {
				_lastCurrentState = _currentState;
				_currentState.OnLeave ();
			}
			stateTime = 0;
			_currentState = value;
			_currentState.OnEnter ();
		}
	}


	#region Interface

	/// <summary>
	/// 更新状态
	/// </summary>
	/// <param name="dt">Dt.</param>
	public void UpdateState(float dt){
		if (isPause) {
			pauseTime += dt;
			return;
		}

		globalTime += dt;

		if (_currentState != null) {
			stateTime += dt;
			_currentState.OnUpdate (dt);
		}

		checkStateTransaction ();
	}

	/// <summary>
	/// 添加状态转移
	/// </summary>
	/// <param name="_ss">Ss.</param>
	/// <param name="_time">Time.</param>
	public void ByStateTimeTranstionsState(SimpleState _ss, float _time){
		_stateTransaction.Add (new StateTransactionData (_time, _ss));
	}

	/// <summary>
	/// 暂停
	/// </summary>
	public void Pause(){
		pauseTime = 0;
		isPause = true;
	}

	/// <summary>
	/// 恢复暂停
	/// </summary>
	public void Recove(){
		isPause = false;
	}

	/// <summary>
	/// 获取当前状态
	/// </summary>
	/// <returns>The current state.</returns>
	public SimpleState GetCurrentState(){
		return currentState;
	}

	/// <summary>
	/// 获取上个状态
	/// </summary>
	/// <returns>The last state.</returns>
	public SimpleState GetLastState(){
		return _lastCurrentState;
	}

	/// <summary>
	/// 设置状态
	/// </summary>
	/// <param name="state">State.</param>
	public void SetState(SimpleState state){
		if (IsState (state))
			return;

		currentState = state;
	}

	/// <summary>
	/// 添加状态
	/// </summary>
	/// <param name="_s">S.</param>
	/// <param name="_onEnter">On enter.</param>
	/// <param name="_onUpdate">On update.</param>
	/// <param name="_onExit">On exit.</param>
	public SimpleState AddState(SimpleState _s, Action _onEnter = null, Action<float> _onUpdate = null, Action _onExit = null){
		if (_states.ContainsKey (_s.stateName))
			return _states [_s.stateName];

		_s.SetAction (_onEnter, _onUpdate, _onExit);
		_states.Add (_s.stateName, _s);
		return _s;
	}

	public T AddState<T>(Action _onEnter = null, Action<float> _onUpdate = null, Action _onExit = null) where T : SimpleState, new(){
		T t = new T ();
		t.stateName = typeof(T).ToString ();
		AddState (t, _onEnter, _onUpdate, _onExit);
		return t;
	}

	/// <summary>
	/// 当前是否为改状态
	/// </summary>
	/// <returns><c>true</c> if this instance is state the specified _s; otherwise, <c>false</c>.</returns>
	/// <param name="_s">S.</param>
	public bool IsState(SimpleState _s){
		if (_s == null)
			return false;
		
		if (currentState != null && currentState.stateName == _s.stateName)
			return true;

		return false;
	}

	/// <summary>
	/// 刷新状态时间
	/// </summary>
	public void RefreshStateTime(){
		stateTime = 0;
	}

	#endregion

	#region Private

	/// <summary>
	/// 检查状态转移
	/// </summary>
	void checkStateTransaction(){
		for(int i = 0;i < _stateTransaction.Count;i++){
			if (globalTime >= _stateTransaction [i].time) {
				SetState (_stateTransaction [i].state);
				_stateTransaction.RemoveAt (i);
				i--;
			}
		}
	}

	#endregion

}
